import React, { useState, useEffect } from 'react';
import { obj_str_trim, obj_empty, get_num, BtSwitch, obj_str, CkValue, useCheck, Dlg, useForm, is_empty, ck_empty,
    IconInput, for_obj, obj_bool, IkCheck, IkInput, IkSelect, loc } from 'sui';
import { ck_num, ck_ascii } from 'nui';
import { get_plc_type } from '../cmd/base';
import { ck_k, no_array } from '../cmd/ck';

const DbValue = ({ open, setOpen, hcmd, cur }) => {
    const [value, setValue] = useState();
    const form = useForm(setValue);

    useEffect(() => {
        if (!open) {
            return;
        }

        if (obj_empty(cur)) {
            setValue({});
        }
        else {
            const cmd = {};
            const tmp = cur.split(".");

            if (tmp[0]) {
                cmd["db"] = tmp[0];
            }

            if (tmp[1]) {
                cmd["dbx"] = tmp[1];
            }

            if (tmp[2]) {
                cmd["offset"] = tmp[2];
            }

            setValue(cmd);
        }
    }, [open, cur]);

    const hdone = () => {
        const ck = {
            db: (v) => ck_ascii(v, loc("mg_288")),
            dbx: (v) => ck_num(v, loc("mg_289")),
            offset: (v) => {
                if (!v) {
                    return null;
                }

                return ck_num(v, loc("mg_290"));
            }
        };

        if (!form.hcheck(ck, value)) {
            return;
        }

        form.hclear();
        setOpen(false);

        let cmd = `${obj_str(value, "db")}.${get_num(value, "dbx")}`;

        const offset = obj_str(value, "offset");
        if (offset) {
            cmd += `.${offset}`;
        }

        hcmd(cmd);
    };

    const hcancel = () => {
        form.hclear();
        setOpen(false);
    };

    return (
        <Dlg open={open} title={loc("pbq")} hcancel={hcancel} hcmd={hdone} name="code">
            <IkInput label={loc("mg_288")} name="db" form={form} value={value}/>
            <IkInput label={loc("mg_289")} name="dbx" form={form} value={value}/>
            <IkInput label={loc("mg_290")} name="offset" form={form} value={value}/>
        </Dlg>
    );
};

const ValueDlg = ({ open, setOpen, hcmd, umd, main, ptype, cus=false, fix }) => {
    const [open_db, openDb] = useState(false);
    const [opck, opCk, hcheck] = useCheck();
    const [value, setValue] = useState();
    const [check, setCheck] = useState(false);
    const [ck_le, ckLe] = useState(false);
    const form = useForm(setValue);

    useEffect(() => {
        if (!open) {
            return;
        }

        const cur = umd.cur;

        if (obj_empty(cur)) {
            setValue({});
            setCheck(false);
            ckLe(false);
        }
        else {
            const cmd = {
                ...cur,
            };

            if (cmd.t === "c") {
                cmd["t"] = cmd.cu;
            }

            setValue(cmd);

            const c = get_num(cur, "c");
            setCheck(c > 0);
            ckLe(obj_bool(cur, "le"));
        }
    }, [open, umd.cur]);

    useEffect(() => {
        if (no_array(obj_str(value, "t"), ptype)) {
            setCheck(false);
        }
    }, [value, ptype]);

    const hdone = () => {
        const kset = new Set();
        const mset = new Set();
        const rset = new Set();

        const cur = umd.cur;
        const fin = umd.fin;

        if (!obj_empty(fix)) {
            for_obj(fix.f, (k, v) => rset.add(k));
        }

        if (!is_empty(main)) {
            const k = obj_str(cur, "k");
            const m = obj_str(cur, "m");

            if (fin === "copy") {
                main.forEach(d => {
                    kset.add(obj_str(d, "k"));
                    mset.add(obj_str(d, "m"));
                });
            }
            else {
                main.forEach(d => {
                    if (d.k !== k) {
                        kset.add(obj_str(d, "k"));
                    }

                    if (d.m !== m) {
                        mset.add(obj_str(d, "m"));
                    }
                });
            }
        }

        const ck = {
            k: (v) => {
                if (cus && ptype === "s7") {
                    return null;
                }

                let e = ck_ascii(v, loc("pbq"));
                if (e) {
                    return e;
                }

                if (kset.has(v)) {
                    return loc("cmd_57");
                }

                e = ck_k(obj_str(value, "t"), v, ptype);
                if (e) {
                    return e;
                }

                return null;
            },
            m: (v) => {
                const e = ck_ascii(v, loc("cmd_44"));
                if (e) {
                    return e;
                }

                if (mset.has(v)) {
                    return loc("cmd_57");
                }

                if (rset.has(v)) {
                    return loc("mg_284");
                }

                return null;
            },
            t: (v) => ck_empty(v, loc("sjlx")),
            s: (v) => {
                if (ptype === "s7" && obj_str(value, "t") === "string") {
                    return ck_num(v, loc("zh_14"));
                }

                return null;
            },
            c: (v) => {
                if (!check) {
                    return null;
                }

                return ck_num(v, loc("szgs"));
            }
        };

        if (!form.hcheck(ck, value)) {
            return;
        }

        form.hclear();

        setOpen(false);

        const t = obj_str(value, "t");

        const cmd = {
            k: obj_str(value, "k"),
            m: obj_str(value, "m"),
            t: t,
        };

        if (t === "string" && ptype === "s7") {
            cmd["s"] = get_num(value, "s");
        }

        const plc_type = get_plc_type(ptype);
        const f = plc_type.find(d => d.id === t);

        if (f) {
            cmd["t"] = t;
        }
        else {
            cmd["t"] = "c";
            cmd["cu"] = t;
        }

        if (ck_le) {
            cmd["le"] = true;
        } else {
            cmd["le"] = false;
        }

        if (check) {
            cmd["c"] = get_num(value, "c");

            if (t === "char") {
                cmd["r"] = obj_bool(value, "r");
                cmd["a"] = obj_bool(value, "a");
            }
        }

        if (t === "string") {
            cmd["r"] = obj_bool(value, "r");
        }

        hcmd(cmd);
    };

    const ckdes = {
        k: loc("pbq"),
        m: loc("mbq")
    };

    const hcancel = () => {
        form.hclear();
        setOpen(false);
    };

    const plcType = () => {
        const plc_type = get_plc_type(ptype);

        const ret = [
            ...plc_type
        ];

        return ret;
    };

    const getTrim = () => {
        const t = obj_str(value, "t");
        if (t === "string" || (t === "char" && check)) {
            return <IkCheck label={loc("zw_34")} name="r" form={form} value={value}/>;
        }
        return null;
    };

    const getAll = () => {
        const t = obj_str(value, "t");
        if (t === "char" && check) {
            return <IkCheck label={loc("zw_35")} name="a" form={form} value={value}/>;
        }

        return null;
    };

    const getLen = () => {
        if (ptype !== "s7") {
            return null;
        }

        const t = obj_str(value, "t");
        if (t !== "string") {
            return null;
        }

        return <IkInput label={loc("zh_14")} name="s" form={form} value={value}/>;
    };

    const hdb = (val) => {
        setValue({
            ...value,
            k: val,
        });
    };

    const getLe = () => {
        if (ptype !== "s7") {
            return null;
        }

        return <BtSwitch checked={ck_le} hcmd={v => ckLe(v)}>{loc("mg_294")}</BtSwitch>;
    };

    const getK = () => {
        if (cus && ptype === "s7") {
            return null;
        }

        if (ptype === "s7") {
            return <IconInput label={ckdes.k} name="k" form={form} value={value} hcmd={() => openDb(true)}/>;
        }

        return <IkInput label={ckdes.k} name="k" form={form} value={value}/>;
    };

    return (
        <Dlg open={open} title={loc("cmd_59")} hcancel={hcancel} hcmd={() => hcheck(value, ckdes, hdone)} name="code">
            {getK()}
            <IkInput label={ckdes.m} name="m" form={form} value={value}/>
            <IkSelect label={loc("sjlx")} name="t" form={form} value={value} lst={plcType()}/>
            {getLen()}
            {getTrim()}
            {getLe()}
            <BtSwitch checked={check} hcmd={v => setCheck(v)} disabled={no_array(obj_str(value, "t"), ptype)}>{loc("cmd_74")}</BtSwitch>
            <IkInput disabled={!check} label={loc("szgs")} name="c" form={form} value={value}/>
            {getAll()}
            <CkValue setOpen={opCk} open={opck} value={value} des={ckdes} setValue={setValue} hcmd={hdone}/>
            <DbValue open={open_db} setOpen={openDb} cur={obj_str(value, "k")} hcmd={hdb}/>
        </Dlg>
    );
};

const FixValue = ({ open, setOpen, hcmd, cur, main, row }) => {
    const [opck, opCk, hcheck] = useCheck();
    const [value, setValue] = useState();
    const form = useForm(setValue);

    useEffect(() => {
        if (!open) {
            return;
        }

        if (obj_empty(cur)) {
            setValue({});
        }
        else {
            setValue(cur);
        }
    }, [open, cur]);

    const hdone = () => {
        const mset = new Set();
        const rset = new Set();

        if (!obj_empty(main)) {
            const tmp = main.v;

            if (!is_empty(tmp)) {
                const m = obj_str(cur, "m");

                tmp.forEach(d => {
                    if (d.m !== m) {
                        mset.add(obj_str(d, "m"));
                    }
                });
            }
        }

        if (!is_empty(row)) {
            const m = obj_str(cur, "m");

            row.forEach(d => {
                if (d.m !== m) {
                    rset.add(obj_str(d, "m"));
                }
            });
        }

        const ck = {
            m: (v) => {
                let e = ck_ascii(v, loc("mbq"));
                if (e) {
                    return e;
                }

                if (mset.has(v)) {
                    return loc("mg_283");
                }

                if (rset.has(v)) {
                    return loc("cmd_57");
                }

                return null;
            },
            v: (t) => ck_empty(t, loc("cmd_60")),
        };

        if (!form.hcheck(ck, value)) {
            return;
        }

        const cmd = {
            m: value.m,
            v: obj_str_trim(value, "v"),
        };

        form.hclear();
        setOpen(false);

        hcmd(cmd);
    };

    const ckdes = {
        m: loc("mbq"),
    };

    const hcancel = () => {
        form.hclear();
        setOpen(false);
    };

    return (
        <Dlg open={open} title={loc("zw_48")} hcancel={hcancel} hcmd={() => hcheck(value, ckdes, hdone)} name="code">
            <IkInput label={ckdes.m} name="m" form={form} value={value}/>
            <IkInput label={loc("cmd_60")} name="v" form={form} value={value}/>
            <CkValue setOpen={opCk} open={opck} value={value} des={ckdes} setValue={setValue} hcmd={hdone}/>
        </Dlg>
    );
};

export {DbValue, FixValue, ValueDlg};
